package band.wukong.practice.javase.core.io.file;

import band.wukong.practice.util.mess.PrintUtils;

import java.io.File;
import java.io.FilenameFilter;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Pattern;

/**
 * Desc: 遍历目录下文件
 * Author: sunjs
 * Date: 2009-12-15 16:17:15
 */
public final class Directory {

    /**
     * A two-tuple for returning a pair of objects:
     */
    public static class TreeInfo implements Iterable<File> {
        public List<File> files = new ArrayList<File>();
        public List<File> dirs = new ArrayList<File>();

        // The default iterable element is the file list:
        public Iterator<File> iterator() {
            return files.iterator();
        }

        void addAll(TreeInfo other) {
            files.addAll(other.files);
            dirs.addAll(other.dirs);
        }

        public String toString() {
            return "dirs: " + PrintUtils.pformat(dirs) +
                    "\n\nfiles: " + PrintUtils.pformat(files);
        }
    }

    /**
     * 取得目录下匹配某种正则表达式的所有文件。
     *
     * @param dir   需要匹配的目录
     * @param regex 需要匹配的文件的名称的正则表达式
     * @return
     */
    public static File[] local(File dir, final String regex) {
        return dir.listFiles(new FilenameFilter() {
            private Pattern pattern = Pattern.compile(regex);
            public boolean accept(File dir, String name) {
                return pattern.matcher(new File(name).getName()).matches();
            }
        });
    }

    /**
     * 取得目录下匹配某种正则表达式的所有文件。
     *
     * @param path  需要匹配的目录
     * @param regex 需要匹配的文件的名称的正则表达式
     * @return
     */
    public static File[] local(String path, final String regex) { // Overloaded
        return local(new File(path), regex);
    }



    /**
     * 取得目录下匹配某种正则表达式的所有文件
     *
     * @param start
     * @param regex
     * @return
     */
    public static TreeInfo walk(String start, String regex) { // Begin recursion
        return recurseDirs(new File(start), regex);
    }

    public static TreeInfo walk(File start, String regex) { // Overloaded
        return recurseDirs(start, regex);
    }

    public static TreeInfo walk(File start) { // Everything
        return recurseDirs(start, ".*");
    }

    public static TreeInfo walk(String start) {
        return recurseDirs(new File(start), ".*");
    }

    static TreeInfo recurseDirs(File startDir, String regex) {
        TreeInfo result = new TreeInfo();
        for (File item : startDir.listFiles()) {
            if (item.isDirectory()) {
                result.dirs.add(item);
                result.addAll(recurseDirs(item, regex));
            } else // Regular file
                if (item.getName().matches(regex))
                    result.files.add(item);
        }
        return result;
    }

    // Simple validation test:
    public static void main(String[] args) {
        // All files beginning with 'T'
        for (File file : Directory.local("./src", "T.*\\.java")) {
            System.out.println(file);
        }

        System.out.println("===================================");

        // All Java files beginning with 'T':
        for (File file : Directory.walk("./src", "T.*\\.java")) {
            System.out.println(file);
        }

        System.out.println("----------------------");

        // Class files containing "Z" or "z":
        for (File file : Directory.walk("./tarena", ".*[Zz].*\\.class")) {
            System.out.println(file);
        }

        System.out.println("----------------------");

        PrintUtils.pprint(Directory.walk("./src").dirs);    //All dirs
        PrintUtils.pprint(Directory.walk("./src").files);   //All files


    }
    //TODO [Undoc] 可以整理到util中
}
